package jp.sourceforge.akjrcp.videotools.subtitlemaker;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.InputEvent;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.Panel;

public  class SelectableFigureList extends Panel{
LineBorder selectedBorder; 
MarginBorder notSelectedBorder;
Figure lastSelected;

private Figure[] lastSelections=new Figure[0];
private List<SelectionChangeListener> selectionChangeListener=new ArrayList<SelectionChangeListener>();

public SelectableFigureList(){
	selectedBorder = new LineBorder();
	selectedBorder.setColor(ColorConstants.green);
	selectedBorder.setWidth(2);
	
	notSelectedBorder=new MarginBorder(2);
	this.setBorder(notSelectedBorder);
	
	addMouseListener(new MouseListener() {

		

		public void mousePressed(org.eclipse.draw2d.MouseEvent mouseEvent) {
			List<IFigure> list=getChildren();
			Figure selected=null;
			for (int i = 0; i < list.size(); i++) {
				Figure f=(Figure) list.get(i);
				if(f.getBounds().contains(mouseEvent.x, mouseEvent.y)){
					selected=f;
					break;
				}
			}
			
			if(selected!=null){
				
			
			
			if(mouseEvent.button==1){//left click
			if((mouseEvent.getState() & InputEvent.CONTROL)>0){
				
				setSelection(selected,!isSelection(selected));
			}else if((mouseEvent.getState() & InputEvent.SHIFT)>0){
				//
				selectBetween(selected);
			}else{
				boolean last=!isSelection(selected);
				unselectAll();
				
				setSelection(selected,last);
				
			}
			}else if(mouseEvent.button==3){//right click
				
			}
			
			lastSelected=selected;
			}
			
			checkSelectionChanged();
		}

		public void mouseReleased(MouseEvent arg0) {
			
		}

		public void mouseDoubleClicked(MouseEvent event){
				

		}

	});
}

protected void checkSelectionChanged() {
	Figure[] newSelections=getSelectionFigures();
	boolean selectionChanged=false;
	if(newSelections.length!=lastSelections.length){
		selectionChanged=true;
	}
	if(!selectionChanged){
		for (int i = 0; i < newSelections.length; i++) {
			if(newSelections[i]!=lastSelections[i]){
				return;
			}
		}
		selectionChanged=true;
	}
	if(selectionChanged){
		fireSelectionChange(lastSelections,newSelections);
	}
}

private void selectBetween(Figure selected){
	int lastIndex=0;
	int selectedIndex=0;
	List<IFigure> list=getChildren();
	
	for (int i = 0; i < list.size(); i++) {
		Figure f=(Figure) list.get(i);
		if(f==selected){
			selectedIndex=i;
			
		}
		if(lastSelected!=null && f==lastSelected){
			lastIndex=i;
		}
	}
	int start,end;
	if(lastIndex>selectedIndex){
		start=selectedIndex;
		end=lastIndex;
	}else{
		start=lastIndex;
		end=selectedIndex;
	}
	
	for(int i=start;i<=end;i++){
		setSelection(((Figure)list.get(i)),true);
	}
	
}
private void unselectAll(){
	List<IFigure> list=getChildren();
	
	for (int i = 0; i < list.size(); i++) {
		Figure f=(Figure) list.get(i);
		setSelection(f,false);
	}
}

public void selectAll(){
	List<IFigure> list=getChildren();
	
	for (int i = 0; i < list.size(); i++) {
		Figure f=(Figure) list.get(i);
		setSelection(f,true);
	}
	checkSelectionChanged();
}

public Figure[] getSelectionFigures(){
	List<Figure> list=new ArrayList<Figure>();
	Figure figures[]=(Figure[]) this.getChildren().toArray(new Figure[0]);
	//log.infofigures:"+figures.length);
	for (int i = 0; i < figures.length; i++) {
		
			
			if(isSelection(figures[i])){
			list.add(figures[i]);
			}
		
		
	}
	return  list.toArray(new Figure[0]);
}

public void addFigure(Figure figure){
	setSelection(figure,false);
	add(figure);
	
	this.repaint();
}

public boolean isSelection(Figure figure){
	return figure.getBorder()!=null && figure.getBorder()==selectedBorder;
}

public void setSelection(Figure figure,boolean bool){
	
	
	if(bool){
		
		figure.setBorder(selectedBorder);
	}else{
		figure.setBorder(notSelectedBorder);
	}
	figure.repaint();
	
}
private void fireSelectionChange(Figure[] oldSelections,Figure[] newSelections){
	   synchronized(this){
		   SelectionChangeListener[] listeners=selectionChangeListener.toArray(new SelectionChangeListener[selectionChangeListener.size()]);
		   for (int i = 0; i < listeners.length; i++) {
			   listeners[i].selectionChanged(this,oldSelections, newSelections);
		}
	   }
}
public synchronized void removeSelectionChangeListener(SelectionChangeListener listener){
    selectionChangeListener.remove(listener);   
   }
   
   public synchronized void addSelectionChangeListener(SelectionChangeListener listener){
	   selectionChangeListener.add(listener);   
      }
}
